package com.tuzhi.convert.mq;


import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tuzhi.common.domain.ResultBO;
import com.tuzhi.common.helper.ResultHelper;
import com.tuzhi.convert.dto.FilesModelDto;
import com.tuzhi.convert.httpclient.FileStoreApi;
import com.tuzhi.convert.utils.CadFileTypeUtils;
import com.tuzhi.convert.utils.ConverterUtils;
import com.tuzhi.convert.utils.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.io.File;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;


/**
 * 转换任务
 */
public class MakeConvertTask implements Callable {
    Logger log = LoggerFactory.getLogger(MakeConvertTask.class);
    static final ObjectMapper MAPPER = new ObjectMapper();
    private FilesModelDto filesModelDto;
    private Callback callback;

    private FileStoreApi fileStoreApi = SpringUtils.getBean(FileStoreApi.class);
    private String cadFilePath;
    private String stpFilePath;
    private String unRarZipFilePath;

    public MakeConvertTask(FilesModelDto filesModelDto, FileStoreApi fileStoreApi, String cadFilePath, String stpFilePath
            , String unRarZipFilePath, Callback callback) {
        this.filesModelDto = filesModelDto;
        this.callback = callback;
        this.fileStoreApi = fileStoreApi;
        this.cadFilePath = cadFilePath;
        this.stpFilePath = stpFilePath;
        this.unRarZipFilePath = unRarZipFilePath;
    }

    public MakeConvertTask(FilesModelDto filesModelDto, String cadFilePath, String stpFilePath, String unRarZipFilePath, Callback callback) {
        this.filesModelDto = filesModelDto;
        this.callback = callback;
        this.cadFilePath = cadFilePath;
        this.stpFilePath = stpFilePath;
        this.unRarZipFilePath = unRarZipFilePath;
    }

    @Override
    public Object call() throws Exception {
        Map dataMap = new HashMap();
        Map statMap = new HashMap();
        dataMap.put("data", statMap);
        ResultBO resultBO;
        File cadFile = null;
        File stpFile = null;
        try {
            log.info("当前线程名：：：{}，fileStoreApi={}", Thread.currentThread().getName(), fileStoreApi);
            //1.更新模型状态为转换中：converting
            statMap.put("status", "converting");
            fileStoreApi.setStatus(dataMap, filesModelDto.getId());
            String fileType = CadFileTypeUtils.getCadFileType(filesModelDto.getCadFileName());
            String fileName = String.format("%s%s", filesModelDto.getId(), fileType);
            //2.下载模型文件
            cadFile = fileStoreApi.getCadFile(cadFilePath, fileName, forestProgress -> {
                System.out.println("total bytes: " + forestProgress.getTotalBytes());   // 文件大小
                System.out.println("current bytes: " + forestProgress.getCurrentBytes());   // 已下载字节数
                System.out.println("progress: " + Math.round(forestProgress.getRate() * 100) + "%");  // 已下载百分比
                if (forestProgress.isDone()) {   // 是否下载完成
                    log.info("--------   Download Completed!   --------");
                }
            }, filesModelDto.getCadFileUrl());
            if (cadFile == null) {
                return ResultHelper.error("下载模型文件失败，ModelId=" + filesModelDto.getId());
            }
            String filePath = Paths.get(cadFilePath, fileName).toString();
            String stpFileName = String.format("%s.stp", filesModelDto.getId());
            String targetPath = Paths.get(stpFilePath, stpFileName).toString();
            log.warn("fileType={}", fileType);
            int result = 1;
            if (".prt".equalsIgnoreCase(fileType)) {
                log.info("convert4Prt {} {}", filePath, targetPath);
                result = ConverterUtils.convert4Prt(filePath, targetPath);
//                result = ConverterUtils.convert4X_T(filePath, targetPath);//使用转换x_t格式的命令也可以转换prt格式，但很慢！！
            } else if (".x_t".equalsIgnoreCase(fileType)) {
                log.info("convert4X_T {} {}", filePath, targetPath);
                result = ConverterUtils.convert4X_T(filePath, targetPath);
            } else if (".prt.1".equalsIgnoreCase(fileType)) {
                log.info("convert4Prt_num {} {}", filePath, targetPath);
                result = ConverterUtils.convert4Prt_num(filePath, targetPath);
            } else if (".zip".equalsIgnoreCase(fileType) || ".rar".equalsIgnoreCase(fileType)) {
                log.info("convert4zip_rar {} {}", filePath, targetPath);
                String unRarZipPath = Paths.get(unRarZipFilePath, filesModelDto.getId().toString()).toString();
                result = ConverterUtils.convert4zip_rar(filePath, targetPath, unRarZipPath, true);
            }
            log.warn("result={}", result);
            if (result != 0) {
                log.info("转换模型失败，modelId={}", filesModelDto.getId());
                statMap.put("status", "error");
                fileStoreApi.setStatus(dataMap, filesModelDto.getId());
                return ResultHelper.error("转换模型失败，modelId=" + filesModelDto.getId());
            }
            //3.上传结果
            resultBO = ResultHelper.error();
            stpFile = sendResult(targetPath, resultBO);
            if (resultBO.isSuccess()) {
                statMap.put("status", "converted");
            } else {
                log.info("上传转换后的stp文件失败，modelId={}", filesModelDto.getId());
                statMap.put("status", "error");
            }
            resultBO = fileStoreApi.setStatus(dataMap, filesModelDto.getId());
            log.info("{},完成任务，当前线程名={}", filesModelDto.getId(), Thread.currentThread().getName());
            return resultBO;
        } catch (Exception exception) {
            log.error("modelId=" + filesModelDto.getId() + ",执行转换任务出错。", exception);
            statMap.put("status", "error");
            resultBO = fileStoreApi.setStatus(dataMap, filesModelDto.getId());
            log.info(JSON.toJSONString(resultBO));
            return ResultHelper.error(exception.getMessage());
        } finally {
            if (cadFile != null) {
                cadFile.delete();
            }
            if (stpFile != null) {
                stpFile.delete();
            }
            // 执行回调
            callback.onComplete(filesModelDto.getId());
        }
    }

    /**
     * 当使用convert4X_T转换文件是会打开一个窗口转换比较慢，会出现文件延迟时间，所以写了个延迟方法
     *
     * @param targetPath
     * @param resultBO
     * @return
     * @throws InterruptedException
     */
    private File sendResult(String targetPath, ResultBO resultBO) throws InterruptedException {
        File stpFile = new File(targetPath);
        int count = 1;
        while (count <= 5 && !stpFile.exists()) {
            log.info("没有找到转换后的stp文件={},第{}次", targetPath, count);
            ++count;
            Thread.sleep(1000 * count + 1000);
            stpFile = new File(targetPath);
        }
        if (stpFile.exists()) {
            ResultBO result = fileStoreApi.sendResult(stpFile, filesModelDto.getId());
            BeanUtils.copyProperties(result, resultBO);
        }
        return stpFile;
    }

}

